"""
本代码由[Tkinter布局助手]生成
官网:https://www.pytk.net
QQ交流群:905019785
在线反馈:https://support.qq.com/product/618914
"""
from tkinter import filedialog, messagebox, ttk
import pyvista as pv
from scipy.io import loadmat
import numpy as np
import random
from tkinter import *
from tkinter.ttk import *
class WinGUI(Tk):
    def __init__(self):
        super().__init__()
        self.__win()
        self.tk_select_box_m8mjt893 = self.__tk_select_box_m8mjt893(self)
        self.tk_text_m8mjtsv2 = self.__tk_text_m8mjtsv2(self)
        self.tk_button_m8mjv1os = self.__tk_button_m8mjv1os(self)
        self.tk_label_m8mk0iko = self.__tk_label_m8mk0iko(self)
        self.tk_label_m8mkhz1m = self.__tk_label_m8mkhz1m(self)
        self.tk_input_m8mkj6m9 = self.__tk_input_m8mkj6m9(self)
        self.tk_button_m8mkkhw2 = self.__tk_button_m8mkkhw2(self)
    def __win(self):
        self.title("2D桁架单元静力分析后处理器")
        # 设置窗口大小、居中
        width = 500
        height = 310
        screenwidth = self.winfo_screenwidth()
        screenheight = self.winfo_screenheight()
        geometry = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
        self.geometry(geometry)
        self.resizable(width=False, height=False)
    def scrollbar_autohide(self,vbar, hbar, widget):
        """自动隐藏滚动条"""
        def show():
            if vbar: vbar.lift(widget)
            if hbar: hbar.lift(widget)
        def hide():
            if vbar: vbar.lower(widget)
            if hbar: hbar.lower(widget)
        hide()
        widget.bind("<Enter>", lambda e: show())
        if vbar: vbar.bind("<Enter>", lambda e: show())
        if vbar: vbar.bind("<Leave>", lambda e: hide())
        if hbar: hbar.bind("<Enter>", lambda e: show())
        if hbar: hbar.bind("<Leave>", lambda e: hide())
        widget.bind("<Leave>", lambda e: hide())
    
    def v_scrollbar(self,vbar, widget, x, y, w, h, pw, ph):
        widget.configure(yscrollcommand=vbar.set)
        vbar.config(command=widget.yview)
        vbar.place(relx=(w + x) / pw, rely=y / ph, relheight=h / ph, anchor='ne')
    def h_scrollbar(self,hbar, widget, x, y, w, h, pw, ph):
        widget.configure(xscrollcommand=hbar.set)
        hbar.config(command=widget.xview)
        hbar.place(relx=x / pw, rely=(y + h) / ph, relwidth=w / pw, anchor='sw')
    def create_bar(self,master, widget,is_vbar,is_hbar, x, y, w, h, pw, ph):
        vbar, hbar = None, None
        if is_vbar:
            vbar = Scrollbar(master)
            self.v_scrollbar(vbar, widget, x, y, w, h, pw, ph)
        if is_hbar:
            hbar = Scrollbar(master, orient="horizontal")
            self.h_scrollbar(hbar, widget, x, y, w, h, pw, ph)
        self.scrollbar_autohide(vbar, hbar, widget)
    def __tk_select_box_m8mjt893(self,parent):
        cb = Combobox(parent, state="readonly", )
        cb['values'] = ("undeform_mesh","deform_mesh",
                        "node_Ux","node_Uy","node_Umag",
                        "node_Fx","node_Fy","node_Fmag",
                        "el_strain","el_stress")
        cb.place(x=20, y=120, width=160, height=30)
        return cb
    def __tk_text_m8mjtsv2(self,parent):
        text = Text(parent)
        text.place(x=200, y=40, width=280, height=250)
        return text
    def __tk_button_m8mjv1os(self,parent):
        btn = Button(parent, text="导入结果文件", takefocus=False,)
        btn.place(x=20, y=40, width=160, height=25)
        return btn
    def __tk_label_m8mk0iko(self,parent):
        label = Label(parent,text="云图变量选择",anchor="center", )
        label.place(x=20, y=80, width=160, height=30)
        return label
    def __tk_label_m8mkhz1m(self,parent):
        label = Label(parent,text="变形云图比例",anchor="center", )
        label.place(x=20, y=160, width=160, height=30)
        return label
    def __tk_input_m8mkj6m9(self,parent):
        ipt = Entry(parent, )
        ipt.place(x=20, y=205, width=160, height=30)
        return ipt
    def __tk_button_m8mkkhw2(self,parent):
        btn = Button(parent, text="更新云图", takefocus=False,)
        btn.place(x=20, y=250, width=160, height=30)
        return btn
class Win(WinGUI):
    def __init__(self, controller):
        self.ctl = controller
        super().__init__()
        self.__event_bind()
        self.__style_config()
        self.ctl.init(self)
    def __event_bind(self):
        self.tk_button_m8mjv1os.bind('<Button-1>',self.ctl.load_mat)
        self.tk_button_m8mkkhw2.bind('<Button-1>',self.ctl.update_plot)
        pass
    def __style_config(self):
        pass
class Controller:
    # 导入UI类后,替换以下的 object 类型,将获得 IDE 属性提示功能
    ui: Win
    def __init__(self):
        # 初始化变量
        self.nodes = None
        self.cells = None
        self.cell_types = None
        self.node_datas = None
        self.cell_datas = None
        self.grid = None
    def init(self, ui):
        """
        得到UI实例,对组件进行初始化配置
        """
        self.ui = ui
        # TODO 组件初始化 赋值操作
    def load_mat(self,evt):
        # 打开文件选择对话框
        mat_file_path = filedialog.askopenfilename(title='选择结果文件', 
                                                filetypes=[('Matlab文件', '*.mat')])
        if not mat_file_path:
            return
        # 读取文件内容
        mat_dats=loadmat(mat_file_path)
        node_num=mat_dats['node_num'][0,0]
        elem_num=mat_dats['element_num'][0,0]
        vtk_type=mat_dats['vtk_type'][0,0]
        self.nodes=mat_dats['Node_data'][:,1:]
        self.cells=np.concatenate((np.ones((elem_num,1),dtype=int)*2,mat_dats['connecticity_data'][:,1:]-1),axis=1)
        self.cells.dtype
        self.cell_types=np.full(elem_num,vtk_type, dtype=np.uint8)
        # 生成网格对象
        self.grid = pv.UnstructuredGrid(self.cells, self.cell_types, self.nodes)
        # 设置网格数据
        self.node_datas={"node_ux":mat_dats["node_ux"][0],
                            "node_uy":mat_dats["node_uy"][0],
                            "node_u_mag":mat_dats["node_u_mag"][0],
                            "node_Freact_x":mat_dats["node_Freact_x"][0],
                            "node_Freact_y":mat_dats["node_Freact_y"][0],
                            "node_Freact_mag":mat_dats["node_Freact_mag"][0],}
        self.cell_datas={"element_stress":mat_dats["element_stress"][:,0],
                            "element_strain":mat_dats["element_strain"][:,0]}
        # 输出信息
        self.ui.tk_text_m8mjtsv2.insert(END,f"==>成功读取文件:{mat_file_path}\n")
        # print("<Button-1>事件未处理:",evt)
    def update_plot(self,evt):
        def get_deform_mesh():
            # 得到变形网格
            mesh=self.grid.copy()
            try:
                s=float( self.ui.tk_input_m8mkj6m9.get())
            except Exception as e:
                messagebox.showerror('错误', f'请输入变形比例:{e}')
                return
            mesh.points[:,0]+=self.node_datas["node_ux"]*s
            mesh.points[:,1]+=self.node_datas["node_uy"]*s
            return mesh
        def get_mesh():
            return self.grid.copy()

        # 根据combobox选择的结果数据进行更新
        var_name=self.ui.tk_select_box_m8mjt893.get()
        if var_name=="undeform_mesh":
            p_mesh=get_mesh()
        if var_name=="deform_mesh":
            p_mesh=get_deform_mesh()
        if var_name=="node_Ux":
            p_mesh=get_deform_mesh()
            p_mesh.point_data[var_name]=self.node_datas["node_ux"]
        if var_name=="node_Uy":
            p_mesh=get_deform_mesh()
            p_mesh.point_data[var_name]=self.node_datas["node_uy"]
        if var_name=="node_Umag":
            p_mesh=get_deform_mesh()
            p_mesh.point_data[var_name]=self.node_datas["node_u_mag"]
        if var_name=="node_Fx":
            p_mesh=get_deform_mesh()
            p_mesh.point_data[var_name]=self.node_datas["node_Freact_x"]
        if var_name=="node_Fy":
            p_mesh=get_deform_mesh()
            p_mesh.point_data[var_name]=self.node_datas["node_Freact_y"]
        if var_name=="node_Fmag":
            p_mesh=get_deform_mesh()
            p_mesh.point_data[var_name]=self.node_datas["node_Freact_mag"]
        if var_name=="el_stress":
            p_mesh=get_deform_mesh()
            p_mesh.cell_data[var_name]=self.cell_datas["element_stress"]
        if var_name=="el_strain":
            p_mesh=get_deform_mesh()
            p_mesh.cell_data[var_name]=self.cell_datas["element_strain"]
        try:
            self.ui.tk_text_m8mjtsv2.insert(END,f"==>当前云图:{var_name}\n")
            data_label=var_name
            pv.set_plot_theme('paraview')
            scalar_bar_args={"title":'',"vertical":True,"interactive":True,}
            if var_name=="undeform_mesh" or var_name=="deform_mesh":
                data_label=None
            p_mesh.plot(scalars=data_label,show_edges=True,text=var_name,window_size = [600, 600],
                            line_width=5,interactive=True,cpos=[(0, 0, 5), (0, 0, 0), (0, 1, 0)],scalar_bar_args=scalar_bar_args)
            del p_mesh
        except Exception as e:
            messagebox.showerror('错误', f'更新失败:{e}')
            return
if __name__ == "__main__":
    app = Win(Controller())
    # 启动
    app.mainloop()